package Records.Attributes;

import Records.Database.DuplicateEntry;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPathFactory;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
 *
 * @author Alexander
 */
public class getSongAttributes {

    private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY = DocumentBuilderFactory.newInstance();
    private static final XPathFactory XPATH_FACTORY = XPathFactory.newInstance();
    private static String key, artists, titles, bpms, Danceability, Energy, Acousticness, albumTitles, RssGenres, PreviewURL, PurchaseLink, beatBPM, beatKey;
    static int errCount;
    private static boolean resetNoNum, byPass;
    private static long lastCommandTime;
    private static long CurrentTime;
    private static int limitUsed;
    private static long startTime;

    public static ArrayList<String> parseXml(String artist, String title, boolean bypassDuplicate) {
        System.out.println("getSongAttributes.parseXml(" + artist + ", " + title + ", " + bypassDuplicate + ")");
        errCount = 0;
        byPass = bypassDuplicate;
        artists = artist.trim();
        if (title.contains("(") || title.contains(")")) {
            titles = stripPerenthesis(title);
        } else {
            titles = title;
        }

        ArrayList ItunesValSet = GetItunesInfo.getInfo(titles, artists);
        PreviewURL = ItunesValSet.get(0).toString();
        PurchaseLink = ItunesValSet.get(1).toString();
        albumTitles = ItunesValSet.get(2).toString();
        RssGenres = ItunesValSet.get(3).toString();
        titles = ItunesValSet.get(4).toString();
        artists = ItunesValSet.get(5).toString();

        if (PreviewURL.equals("") || PurchaseLink.equals("") || albumTitles.equals("") || RssGenres.equals("")) {//|| titles.equals("") || artists.equals("")) {
            ArrayList beatportValSet = getBeatportInfo.getInfo(title, artist);
            if (PurchaseLink.equals("")) {
                PurchaseLink = beatportValSet.get(1).toString();
            }
            if (albumTitles.equals("")) {
                albumTitles = beatportValSet.get(2).toString();
            }
            if (RssGenres.equals("")) {
                RssGenres = beatportValSet.get(3).toString();
            }
            //if (titles.equals("")) {
            //titles = beatportValSet.get(4).toString();
            //}
            //if (artists.equals("")) {
            //artists = beatportValSet.get(5).toString();
            //}
            beatBPM = beatportValSet.get(4).toString();
            beatKey = beatportValSet.get(5).toString();

        }
        ArrayList<String> valSet = createValueSet();
        //valSet.add(Path);
        return valSet;
    }

    public static ArrayList createValueSet() {
        System.out.println("getSongAttributes.createValueSet()");

        ArrayList valSet = new ArrayList();
        boolean continuer;
        if (byPass == true) {
            continuer = false;
        } else {
            continuer = DuplicateEntry.isDuplicate(titles, artists);
        }

        if (!continuer) {
            theInfo(artists, titles);
            String Key = "";
            if (bpms.equals("")) {
                bpms = beatBPM;
            }
            if (!key.equals("")) {
                Key = numberToKey();
            } else if (beatKey != null) {
                Key = beatKey;
            }
            String BPM = BPM(bpms);
            String Dance = Dance();
            String EnergyAmount = EnergyAmount();
            String Acoustic = Acoustic();

            valSet.add(titles);
            //System.out.println("TITLE: " + titles);
            valSet.add(artists);
            //System.out.println("ARTIST: " + artists);

            valSet.add(BPM);
            valSet.add(Key);
            valSet.add(Dance);
            valSet.add(EnergyAmount);
            valSet.add(Acoustic);
            valSet.add(albumTitles);
            valSet.add(RssGenres);
            valSet.add(PreviewURL); //FilePathWay
            valSet.add(PurchaseLink);
        } else {
            valSet = null;
        }
        return valSet;
    }

    public static String stripPerenthesis(String titleLine) {
        System.out.println("getSongAttributes.stripPerenthesis(" + titleLine + ")");

        String newTitle = titleLine;
        if (!(titleLine.contains("remix[)]") || titleLine.contains("Remix[)]") || titleLine.contains("edit[)]") || titleLine.contains("mashup[)]"))) {
            newTitle = newTitle.split("[(]")[0];
        }
        return newTitle;
    }

    public static String Dance() {
        System.out.println("getSongAttributes.Dance()");

        String D;
        if (Danceability == null || "".equals(Danceability)) {
            D = "050";
        } else {
            double value = Double.parseDouble(Danceability);
            value = value * 100;
            if (value < 10) {
                D = "00" + value;
            } else if (value < 100 && value > 10) {
                D = "0" + value;
            } else {
                D = "" + value;
            }
            D = D.split("[.]")[0];
        }
        //System.out.println(D);

        return D;
    }

    public static String EnergyAmount() {
        System.out.println("getSongAttributes.EnergyAmount()");

        String E;
        if (Energy == null || "".equals(Energy)) {
            E = "050";
        } else {
            double value = Double.parseDouble(Energy);
            value = value * 100;
            if (value < 10) {
                E = "00" + value;
            } else if (value < 100 && value > 10) {
                E = "0" + value;
            } else {
                E = "" + value;
            }
            E = E.split("[.]")[0];

        }
        //System.out.println(E);

        return E;
    }

    public static String Acoustic() {
        System.out.println("getSongAttributes.Acoustic()");

        String A;
        if (Acousticness == null || "".equals(Acousticness)) {
            A = "050";
        } else {
            double value = Double.parseDouble(Acousticness);
            value = value * 100;
            if (value < 10) {
                A = "00" + value;
            } else if (value < 100 && value > 10) {
                A = "0" + value;
            } else {
                A = "" + value;
            }
            A = A.split("[.]")[0];
            //System.out.println(A);
        }
        return A;
    }

    public static String BPM(String bpm) {
        System.out.println("getSongAttributes.BPM()");

        if (bpm == null || "".equals(bpm)) {
            bpm = "000";
        } else {
            double value = Double.parseDouble(bpm);
            if (value < 10) {
                bpm = "00" + value;
            } else if (value < 100 && value > 10) {
                bpm = "0" + value;
            } else {
                bpm = "" + value;
            }
            bpm = bpm.split("[.]")[0];
        }
        return bpm;
    }

    public static String numberToKey() {
        System.out.println("getSongAttributes.numberToKey()");

        String keys = "unknown";
        switch (key) {
            case "0":
                keys = "C";
                break;
            case "1":
                keys = "C#";
                break;
            case "2":
                keys = "D";
                break;
            case "3":
                keys = "D#";
                break;
            case "4":
                keys = "E";
                break;
            case "5":
                keys = "F";
                break;
            case "6":
                keys = "F#";
                break;
            case "7":
                keys = "G";
                break;
            case "8":
                keys = "G#";
                break;
            case "9":
                keys = "A";
                break;
            case "10":
                keys = "A#";
                break;
            case "11":
                keys = "B";
                break;
        }
        return keys;
    }

    public static void theInfo(String artistLine, String titleLine) {
        System.out.println("getSongAttributes.parseXml(" + artistLine + ", " + titleLine + ")");
        JSONObject sumObject = null;

        try {
            titleLine = titleLine.replaceAll("&", "");
            //String value = "";
            //int count = 0;
            String site = "http://developer.echonest.com/api/v4/song/search?api_key=LXSEHQYDQJBY8GYMO&format=json&artist=" + artistLine.replaceAll(" ", "%20") + "&title=" + titleLine.replaceAll(" ", "%20") + "&results=1&bucket=audio_summary&bucket=song_type&bucket=song_hotttnesss&bucket=song_discovery";
            URL url = null;
            InputStream connection = null;
            try {
                url = new URL(site);
                System.out.println(url);
                //connection = url.openStream();

            } catch (MalformedURLException ex) {
                Logger.getLogger(getSongAttributes.class.getName()).log(Level.SEVERE, null, ex);
            }

            String Path = "";
            InputStream is = url.openStream();

            try {
                timeTrack();
                BufferedReader br = new BufferedReader(new InputStreamReader(is));
                String line = "";
                while ((line = br.readLine()) != null) {
                    Path = Path + line;
                }
                //System.out.println(Path);
            } catch (IOException ex) {
                Logger.getLogger(getSongAttributes.class.getName()).log(Level.SEVERE, null, ex);
            }
            JSONObject outerObject;
            JSONObject objectInArray = null;
            outerObject = new JSONObject(Path);
            JSONObject innerObject = outerObject.getJSONObject("response");
            JSONArray songArray = innerObject.getJSONArray("songs");
            objectInArray = songArray.getJSONObject(0);
            sumObject = objectInArray.getJSONObject("audio_summary");

            try {
                bpms = sumObject.optString("tempo");
            } catch (Exception ex) {
                bpms = "";
                Logger.getLogger(GetItunesInfo.class.getName()).log(Level.SEVERE, null, ex);
            }

            try {
                key = sumObject.optString("key");
            } catch (Exception ex) {
                key = "";
                Logger.getLogger(GetItunesInfo.class.getName()).log(Level.SEVERE, null, ex);
            }

            try {
                Danceability = sumObject.optString("danceability");
            } catch (Exception ex) {
                Danceability = "";
                Logger.getLogger(GetItunesInfo.class.getName()).log(Level.SEVERE, null, ex);
            }

            try {
                Energy = "" + ((Double.parseDouble(sumObject.optString("energy")) + Double.parseDouble(sumObject.optString("valence"))) / 2);
            } catch (Exception ex) {
                Energy = "";
                Logger.getLogger(GetItunesInfo.class.getName()).log(Level.SEVERE, null, ex);
            }
            try {
                Acousticness = sumObject.optString("acousticness");
            } catch (Exception ex) {
                Acousticness = "";
                Logger.getLogger(GetItunesInfo.class.getName()).log(Level.SEVERE, null, ex);
            }

            //System.out.println(bpms);
            //System.out.println(key);
            //System.out.println(Danceability);
            //System.out.println(Energy);
            //System.out.println(Acousticness);
            is.close();
        } catch (JSONException ex) {
            if (!resetNoNum) {
                System.out.println("No numbers...Resetting...");
                String resetTitle = titleLine.replaceAll("[0-9]", "").replace("/", "-");
                resetNoNum = true;
                String sub = "";
                Matcher m = Pattern.compile("\\(([^)]+)\\)").matcher(resetTitle);
                if (m.find()) {
                    sub = m.group(1);
                }
                resetTitle = titleLine.replace(sub, "");
                theInfo(AttributeCleaner.cleanAttribute("Title", resetTitle), artistLine);
            } else {
                bpms = "";
                key = "";
                Danceability = "";
                Energy = "";
                Acousticness = "";

                //System.out.println(bpms);
                //System.out.println(key);
                //System.out.println(Danceability);
                //System.out.println(Energy);
                //System.out.println(Acousticness);
            }
        } catch (IOException ex) {
            Logger.getLogger(getSongAttributes.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public static void timeTrack() {
        System.out.println("getSongAttributes.timeTrack()");
        if (limitUsed == 0) {
            startTime = System.currentTimeMillis() / 1000;
            System.out.println("Setting startTime = " + startTime);
        }
        CurrentTime = System.currentTimeMillis() / 1000;
        long timeInSeconds = (CurrentTime - startTime);
        limitUsed++;
        int outOfLimit = 120;
        System.out.println(limitUsed + " out of " + outOfLimit);
        int timeLeft = (int) (60 - timeInSeconds);
        System.out.println("Time left = " + (timeLeft));
        if ((limitUsed >= (outOfLimit)) && (timeInSeconds < 60)) {
            try {
                System.out.println("Waiting for the next available connection...");
                TimeUnit.SECONDS.sleep(60 - timeInSeconds);
            } catch (InterruptedException ex) {
                Logger.getLogger(getSongAttributes.class.getName()).log(Level.SEVERE, null, ex);
            }
            limitUsed = 1;
            startTime = System.currentTimeMillis() / 1000;
            System.out.println("Resetting startTime = " + startTime);
        } else if (timeInSeconds >= 60) {
            limitUsed = 1;
            startTime = (System.currentTimeMillis() / 1000) + timeLeft;
            System.out.println("Resetting startTime = " + startTime);
        }
    }
}
